use std::ops::Add;

trait Produce {
    fn add_name(&mut self, name: String);
    fn add_age(&mut self, age: i32);
    fn build(self) -> Person;
}

#[derive(Debug)]
struct Person {
    name: String,
    age: i32,
}

struct StudentBuild {
    name: String,
    age: i32,
}

struct SocialBuild {
    name: String,
    age: i32,
}


impl Produce for StudentBuild {
    fn add_name(&mut self, name: String) {
        self.name = name.add(":Student")
    }

    fn add_age(&mut self, age: i32) {
        self.age = age
    }

    fn build(self) -> Person {
        Person {
            name: self.name,
            age: self.age,
        }
    }
}

impl Produce for SocialBuild {
    fn add_name(&mut self, name: String) {
        self.name = name.add(":Social")
    }

    fn add_age(&mut self, age: i32) {
        self.age = age
    }

    fn build(self) -> Person {
        Person {
            name: self.name,
            age: self.age,
        }
    }
}

#[test]
fn main() {
    let mut build = StudentBuild { name: "".to_string(), age: 0 };
    build.add_name(String::from("social"));
    build.add_age(12);

    println!("{:?}", build.build());

    let mut build1 = SocialBuild { name: "".to_string(), age: 0 };
    build1.add_name(String::from("social"));
    build1.add_age(12123);

    println!("{:?}", build1.build());
}
